home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 98
/
Skunkware 98.iso
/
src
/
interp
/
tclStruct1.2.tar.gz
/
tclStruct1.2.tar
/
tclStruct1.2
/
stInfo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-12
|
14KB
|
466 lines
/*
* tclStruct package
* Support 'C' structures in Tcl
*
* Written by Matthew Costello
* (c) 1995 AT&T Global Information Solutions, Dayton Ohio USA
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "stInternal.h"
STRUCT_SCCSID("@(#)tclStruct:stInfo.c 1.3 95/09/12")
/*
* Struct_Typeof
*
* Take an object or type name and return the type
* of the entity.
*
* Returns:
* attached type on success
* NULL and interp->result on error
*/
Struct_TypeDef *
Struct_Typeof(cdata, interp, name)
ClientData cdata;
Tcl_Interp *interp;
CONST char *name;
{
Struct_TypeDef *type;
Struct_Object objbuf;
if ((type = Struct_LookupType(cdata,interp,name)) != NULL) {
return type;
}
if (Struct_GetObject(interp,name,&objbuf) == TCL_OK) {
return objbuf.type;
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* Struct_InfoCmd --
*
* This procedure is invoked to process the "struct_info" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
int
Struct_InfoCmd(cdata, interp, argc, argv)
ClientData cdata;
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
unsigned int length;
Struct_TypeDef *type;
if (cdata == NULL) {
Tcl_AppendResult(interp, "NULL clientData in Struct_InfoCmd",NULL);
return TCL_ERROR;
}
Struct_PkgInfo(cdata,si_cmdCount) += 1;
if (argc < 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" option ?arg arg ...?\"", (char *) NULL);
return TCL_ERROR;
}
#ifdef DEBUG
if (struct_debug & (DBG_COMMAND)) Struct_PrintCommand(argc,argv);
#endif
length = strlen(argv[1]);
switch (argv[1][0]) {
case 'b':
if (strncmp(argv[1], "builtins", length) == 0) {
Tcl_HashEntry *entryPtr;
Tcl_HashSearch search;
char *name;
if (argc > 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " types ?pattern?\"", (char *) NULL);
return TCL_ERROR;
}
for ( entryPtr = Tcl_FirstHashEntry(Struct_TypeHash(cdata), &search);
entryPtr != NULL;
entryPtr = Tcl_NextHashEntry(&search) ) {
if (!(((Struct_TypeDef *)Tcl_GetHashValue(entryPtr))->flags & STRUCT_FLAG_BUILTIN))
continue;
name = Tcl_GetHashKey(Struct_TypeHash(cdata), entryPtr);
if ((argc == 3) && !Tcl_StringMatch(name, argv[2])) {
continue;
}
Tcl_AppendElement(interp, name);
}
return TCL_OK;
}
break;
case 'c':
if (strncmp(argv[1], "count", length) == 0) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" count ?item?\"", (char *) NULL);
return TCL_ERROR;
}
length = strlen(argv[2]);
if (strncmp(argv[2],"command",length) == 0) {
length = Struct_PkgInfo(cdata,si_cmdCount);
} else if (strncmp(argv[2],"read",length) == 0) {
length = Struct_PkgInfo(cdata,si_rdCount);
} else if (strncmp(argv[2],"write",length) == 0) {
length = Struct_PkgInfo(cdata,si_wrCount);
} else if (strncmp(argv[2],"newtype",length) == 0) {
length = Struct_PkgInfo(cdata,si_nNewTypes);
#ifdef ACCESS_TO_INTERPRETER
} else if (strncmp(argv[2],"extype",length) == 0) {
length = Struct_PkgInfo(cdata,si_nExTypes);
#endif
} else if (strncmp(argv[2],"reset",length) == 0) {
Struct_PkgInfo(cdata,si_cmdCount) = 0;
Struct_PkgInfo(cdata,si_rdCount) = 0;
Struct_PkgInfo(cdata,si_wrCount) = 0;
Struct_PkgInfo(cdata,si_nNewTypes) = 0;
Struct_PkgInfo(cdata,si_nExTypes) = 0;
return TCL_OK;
} else {
Tcl_AppendResult(interp, "bad option \"", argv[2],
"\": should be read, write, or newtype",
(char *) NULL);
return TCL_ERROR;
}
sprintf(interp->result, "%d", length );
return TCL_OK;
}
break;
case 'd':
if (strncmp(argv[1], "debug", length) == 0) {
return Struct_DebugInfo(cdata,interp,argc,argv);
}
break;
case 'e':
if (strncmp(argv[1], "exists", length) == 0) {
if (argc != 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" exists objName\"", (char *) NULL);
return TCL_ERROR;
}
interp->result = (STRUCT_GETOBJECT(interp, argv[2])) ? "1" : "0";
return TCL_OK;
}
break;
case 'g':
if (strncmp(argv[1], "generate", length) == 0) {
if (argc > 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" generate ?prefix?\"", (char *) NULL);
return TCL_ERROR;
}
Tcl_AppendResult(interp,
Struct_GenerateName((argc == 3) ? argv[2] : "gen" ),
(char *)NULL );
return TCL_OK;
}
break;
case 'o':
if (strncmp(argv[1], "object", length) == 0) {
Struct_Object objbuf;
if (argc < 3 || argc > 5 ||
(argc > 4 && strncmp(argv[3],"type",strlen(argv[3])) != 0)) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" object obj ?info?\"", (char *) NULL);
return TCL_ERROR;
}
(void) Struct_GetObject(interp,argv[2],&objbuf);
if (argc == 3) {
/* Does object exist? */
interp->result = (objbuf.type != NULL) ? "1" : "0";
Struct_ReleaseType(objbuf.type);
return TCL_OK;
}
if (objbuf.type == NULL) {
return TCL_ERROR;
}
length = strlen(argv[3]);
if (strncmp(argv[3],"address",length) == 0) {
sprintf( interp->result, "%d", (int)objbuf.data );
} else if (strncmp(argv[3],"size",length) == 0) {
sprintf( interp->result, "%d", objbuf.size );
} else if (strncmp(argv[3],"type",length) == 0) {
if (argc > 4) {
type = objbuf.type;
argv[3] = argv[4];
goto type_info;
}
if (objbuf.type->name == NULL) {
Tcl_AppendResult(interp, "object has anonymous type", (char *)NULL );
Struct_ReleaseType(objbuf.type);
return TCL_ERROR;
}
interp->result = objbuf.type->name;
} else {
Tcl_AppendResult(interp, "bad option \"", argv[3],
"\": should be address, size, or type",
(char *) NULL);
Struct_ReleaseType(objbuf.type);
return TCL_ERROR;
}
Struct_ReleaseType(objbuf.type);
return TCL_OK;
}
break;
case 'p':
if (strncmp(argv[1], "patchlevel", length) == 0) {
char *value;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" patchlevel\"", (char *) NULL);
return TCL_ERROR;
}
if ((value = Tcl_GetVar(interp, "struct_patchLevel",
TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)) == NULL)
return TCL_ERROR;
interp->result = value;
return TCL_OK;
}
break;
case 's':
if ((strncmp(argv[1], "sizeof", length) == 0)) {
Struct_Object objbuf;
if (argc!=3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" sizeof type|object\"", (char *) NULL);
return TCL_ERROR;
}
/* Is argv[2] a valid type name? */
if ((type = Struct_LookupType(cdata,interp,argv[2])) != NULL) {
sprintf( interp->result, "%d", type->size );
Struct_ReleaseType(type);
return TCL_OK;
}
/* Is argv[2] an object? */
if (Struct_GetObject(interp,argv[2],&objbuf) == TCL_OK) {
sprintf( interp->result, "%d", objbuf.size );
Struct_ReleaseType(objbuf.type);
return TCL_OK;
}
Tcl_ResetResult(interp);
Tcl_AppendResult(interp,"\"",argv[2],
"\" is neither a valid type nor a valid object",NULL);
return TCL_ERROR;
}
break;
case 't':
if (length < 4)
break;
if ((strncmp(argv[1], "type", length) == 0)) {
if (argc < 3 || argc >> 4) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" type type ?info?\"", (char *) NULL);
return TCL_ERROR;
}
type = Struct_LookupType(cdata,interp,argv[2]);
if (argc == 3) {
/* Does type exist? */
if (type != NULL)
Struct_ReleaseType(type);
interp->result = (type != NULL) ? "1" : "0";
return TCL_OK;
}
if (type == NULL) {
return TCL_ERROR;
}
type_info:
length = strlen(argv[3]);
if (length == 0) { /* Don't match anything */
/*EMPTY*/;
} else if (length >= 2 && strncmp(argv[3],"address",length) == 0) {
sprintf( interp->result, "%p", (void *)type );
} else if (length >= 2 && strncmp(argv[3],"align",length) == 0) {
sprintf( interp->result, "%d", type->align );
} else if (length >= 2 && strncmp(argv[3],"basic",length) == 0) {
interp->result = (type->flags & STRUCT_FLAG_TRACE_BASIC) ?
"1" : "0";
} else if (length >= 2 && strncmp(argv[3],"builtin",length) == 0) {
interp->result = (type->flags & STRUCT_FLAG_BUILTIN) ?
"1" : "0";
} else if (length >= 5 && strncmp(argv[3],"elemnames",length) == 0) {
if (type->flags & STRUCT_FLAG_IS_STRUCT) {
Struct_StructElem *pelem;
for ( pelem = type->u.s.struct_def;
pelem->type != NULL; pelem++ )
Tcl_AppendElement(interp,pelem->name);
}
} else if (length >= 5 && strncmp(argv[3],"elemtype",length) == 0) {
if (type->flags & (STRUCT_FLAG_IS_ARRAY|STRUCT_FLAG_IS_POINTER)) {
if (type->u.a.array_elem->name != NULL)
interp->result = type->u.a.array_elem->name;
}
} else if (length >= 2 && strncmp(argv[3],"endian",length) == 0) {
if (type->flags & STRUCT_FLAG_USE_ENDIAN)
interp->result = (type->flags & STRUCT_FLAG_BIG_ENDIAN) ?
"big" : "little";
} else if (length >= 2 && strncmp(argv[3],"fill",length) == 0) {
if (type->fill != NULL)
interp->result = type->fill;
} else if (length >= 2 && strncmp(argv[3],"flags",length) == 0) {
sprintf( interp->result, "%d", type->flags );
#ifdef STRUCT_FLAG_USE_JUST
} else if (strncmp(argv[3],"justify",length) == 0) {
if (type->flags & STRUCT_FLAG_USE_JUST)
switch (type->flags & STRUCT_FLAG_JUST_MASK) {
case STRUCT_FLAG_JUST_NONE:
interp->result = "none"; break;
case STRUCT_FLAG_JUST_LEFT:
interp->result = "left"; break;
case STRUCT_FLAG_JUST_RIGHT:
interp->result = "right"; break;
case STRUCT_FLAG_JUST_CENTER:
interp->result = "center"; break;
}
#endif /*STRUCT_FLAG_USE_JUST*/
} else if (strncmp(argv[3],"kind",length) == 0) {
switch (type->flags & STRUCT_FLAG_IS_MASK) {
case STRUCT_FLAG_IS_BUILTIN:
interp->result = "builtin"; break;
case STRUCT_FLAG_IS_ARRAY:
interp->result = "array"; break;
case STRUCT_FLAG_IS_STRUCT:
interp->result = "struct"; break;
case STRUCT_FLAG_IS_POINTER:
interp->result = "pointer"; break;
case STRUCT_FLAG_IS_ADDR:
interp->result = "address"; break;
}
} else if (length >= 2 && strncmp(argv[3],"name",length) == 0) {
if (type->name != NULL)
interp->result = type->name;
} else if (length >= 2 && strncmp(argv[3],"nullok",length) == 0) {
if (type->flags & STRUCT_FLAG_USE_NULLOK)
interp->result = (type->flags & STRUCT_FLAG_NULL_OK) ?
"1" : "0";
} else if (strncmp(argv[3],"refcount",length) == 0) {
sprintf( interp->result, "%d", type->refcount - 1 );
} else if (length >= 2 && strncmp(argv[3],"size",length) == 0) {
sprintf( interp->result, "%d", type->size );
} else if (length >= 2 && strncmp(argv[3],"strict",length) == 0) {
interp->result = (type->flags & STRUCT_FLAG_STRICT) ?
"1" : "0";
} else if (strncmp(argv[3],"traceproc",length) == 0) {
sprintf( interp->result, "%p", (void *)type->TraceProc );
} else if (strncmp(argv[3],"unsigned",length) == 0) {
if (type->flags & STRUCT_FLAG_USE_SIGN)
interp->result = (type->flags & STRUCT_FLAG_UNSIGNED) ?
"1" : "0";
} else if (strncmp(argv[3],"varlen",length) == 0) {
interp->result = (type->flags & STRUCT_FLAG_VARLEN) ?
"1" : "0";
} else {
Tcl_AppendResult(interp, "bad option \"", argv[3],
"\": should be address, align, basic, builtin, elemnames",
", elemtype, endian, fill, flags",
#ifdef STRUCT_FLAG_USE_JUST
", justify",
#endif /*STRUCT_FLAG_USE_JUST*/
", kind, name, nullok, refcount, size",
", strict, traceproc, unsigned, or varlen",
(char *) NULL);
Struct_ReleaseType(type);
return TCL_ERROR;
}
Struct_ReleaseType(type);
return TCL_OK;
} else if ((strncmp(argv[1], "typeof", length) == 0)) {
if (argc!=3) {
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" typeof type|object\"", (char *) NULL);
return TCL_ERROR;
}
/* What is type of argv[2]? */
if ((type = Struct_Typeof(cdata,interp,argv[2])) == NULL) {
return TCL_ERROR;
}
if (type->name == NULL) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "no name associated with this type", (char *)NULL );
Struct_ReleaseType(type);
return TCL_ERROR;
}
interp->result = type->name;
Struct_ReleaseType(type);
return TCL_OK;
} else if ((strncmp(argv[1], "types", length) == 0)) {
Tcl_HashEntry *entryPtr;
Tcl_HashSearch search;
char *name;
if (argc > 3) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " types ?pattern?\"", (char *) NULL);
return TCL_ERROR;
}
for ( entryPtr = Tcl_FirstHashEntry(Struct_TypeHash(cdata), &search);
entryPtr != NULL;
entryPtr = Tcl_NextHashEntry(&search) ) {
name = Tcl_GetHashKey(Struct_TypeHash(cdata), entryPtr);
if ((argc == 3) && !Tcl_StringMatch(name, argv[2])) {
continue;
}
Tcl_AppendElement(interp, name);
}
return TCL_OK;
}
break;
case 'v':
if ((strncmp(argv[1], "version", length) == 0)) {
char *value;
if (argc != 2) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
argv[0], " struct_version\"", (char *) NULL);
return TCL_ERROR;
}
if ((value = Tcl_GetVar(interp, "struct_version",
TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)) == NULL)
return TCL_ERROR;
interp->result = value;
return TCL_OK;
}
break;
}
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": should be ",
"count, exists, generate, ",
"object, patchlevel, ",
"sizeof, type, typeof, ",
"types, or version",
(char *)NULL );
return TCL_ERROR;
}